package com.wsx.first.c;

import java.util.Arrays;
import java.util.List;

/**
 * @author: wangshunxi
 * @date: 2022/5/11 14:32
 * @Description:
 */
public class Main9999 {

    public static void main(String[] args) {
        String expression = "3+4*2-1*10/2";
        List<String> values = Arrays.asList("3", "4", "2", "1", "10", "2");
        List<String> operates = Arrays.asList("+", "*", "-", "*", "/");
        AbstractNode head = new SingleNode();
        AbstractNode current = head;
        for (int i = 0; i < operates.size(); i++) {
            AbstractNode abstractNode = null;
            switch (operates.get(i)) {
                case "+":
                    abstractNode = new AddNode();
                    break;
                case "-":
                    abstractNode = new SubtractNode();
                    break;
                case "*":
                    abstractNode = new MultiplyNode();
                    break;
                case "/":
                    abstractNode = new DivideNode();
                    break;
                default:
                    throw new UnsupportedOperationException();

            }
            abstractNode.value = Float.valueOf(values.get(i));
            current.next = abstractNode;
            current = abstractNode;
        }
        SingleNode last = new SingleNode();
        last.value = Float.valueOf(values.get(values.size() - 1));
        current.next = last;
        int deep = values.size();
        resolve(head, deep);
    }

    private static void resolve(AbstractNode head, int deep) {
        //找一个最大优先级
        for (int i = 0; i < deep; i++) {
            core(head);
        }
        System.out.println(head.next.value);
    }

    private static boolean core(AbstractNode head) {
        AbstractNode current = head;
        AbstractNode last = current;
        while (current.next != null) {
            int priority = current.getPriority();
            if (priority > 0) {
                float operate = current.operate();
                current.next.value = operate;
                last.next = current.next;
                current = last.next;
                return true;
            }
            last = current;
            current = current.next;
        }

        current = head;
        last = current;
        while (current.next != null) {
            int priority = current.getPriority();
            if (priority == 0) {
                float operate = current.operate();
                current.next.value = operate;
                last.next = current.next;
                current = last.next;
                return true;
            }
            last = current;
            current = current.next;
        }
        while (current.next != null) {
            int priority = current.getPriority();
            if (priority <= 0) {
                float operate = current.operate();
                current.next.value = operate;
                last.next = current.next;
                current = last.next;
                return true;
            }
            last = current;
            current = current.next;
        }
        head = current;
        System.out.println(current.value);
        return false;
    }

    public static class SingleNode extends AbstractNode implements Operation{


        @Override
        public float operate() {
            return next.value;
        }

        @Override
        public int getPriority() {
            return -1;
        }
    }

    public static class AddNode extends AbstractNode implements Operation{


        @Override
        public float operate() {
            return value + next.value;
        }

        @Override
        public int getPriority() {
            return 0;
        }
    }

    public static class SubtractNode extends AbstractNode {


        @Override
        public float operate() {
            return value - next.value;
        }

        @Override
        public int getPriority() {
            return 0;
        }
    }

    public static class MultiplyNode extends AbstractNode {


        @Override
        public float operate() {
            return value * next.value;
        }

        @Override
        public int getPriority() {
            return 1;
        }
    }

    public static class DivideNode extends AbstractNode {

        @Override
        public float operate() {
            return value / next.value;
        }

        @Override
        public int getPriority() {
            return 1;
        }
    }






    public static class AbstractNode implements Operation{
        protected float value;

        protected AbstractNode next;

        protected AbstractNode pre;

        @Override
        public float operate() {
            return 0;
        }

        @Override
        public int getPriority() {
            return 0;
        }
    }

    public interface Operation {
        float operate();

        int getPriority();
    }
}
